use deadpool_redis::Pool;

mod redis_pool_wrapper;
use anyhow;
use base64;
use deadpool_redis::{cmd, Pipeline};
use reqwest;
use rocket::data::{Data/*, ToByteUnit*/};
use rocket::http::{
    ContentType,
    Method::{Get/*, Post*/},
    /*Status,*/
};
/*
use rocket::outcome::{try_outcome, IntoOutcome};
use rocket::response::{self, status::Custom, Responder};
use rocket::tokio::fs::File;
*/
use rocket::{/*catcher, */route,/* Catcher,*/ Request, /*Response,*/ Route};
use serde_json;
/*
use std::cell::RefCell;
use std::error::Error;
use std::io::Cursor;
use std::path::Path;
*/
use std::path::PathBuf;
/*
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::thread;
*/
//配置
#[derive(Clone)]
pub struct RocketGiteePicturesWrapperConfig {
    //redis 主机IP
    pub redis_host: String,
    //redis端口
    pub redis_port: i32,
    //redis 主机密码
    pub redis_password: String,
    //gitee token
    pub gitee_token: String,
    //gitee账号
    pub gitee_owner: String,
    //仓库名
    pub gitee_repo: String,
    //仓库分支名
    pub gitee_branch: String,
    //文件缓存刷新间隔
    pub gitee_refresh_interval: i32,
}

//图C用自定义route handler
#[derive(Clone)]
pub struct RocketGiteePicturesHandler {
    //handler配置
    pub config: RocketGiteePicturesWrapperConfig,
    //redis线程池
    pub redis_pool: Pool,
}

//加载gitee文件路径到 redis缓存
pub async fn load_git_files_path_to_redis(
    config: &RocketGiteePicturesWrapperConfig,
    pool: &Pool,
) -> Result<(), anyhow::Error> {
    //获取文件列表
    let body = reqwest::get(format!(
        "https://gitee.com/api/v5/repos/{}/{}/git/trees/{}?access_token={}&recursive=1",
        &config.gitee_owner, &config.gitee_repo, &config.gitee_branch, &config.gitee_token
    ))
    .await?
    .text()
    .await?;

    //分解结果json
    let v: serde_json::Value = serde_json::from_str(&body)?;
    //文件列表
    let tree = v.get("tree");
    match tree {
        Some(fs) => {
            let filearray = fs.as_array();

            match filearray {
                Some(files) => {
                    //获取连接
                    let mut redisconn = pool.get().await?;
                    let mut pipeline = Pipeline::new();
                    for file in files {
                        //文件路径
                        let filepath = file.get("path").unwrap().as_str().unwrap();
                        //文件链接
                        let fileurl = file.get("url").unwrap().as_str().unwrap();

                        //缓存链接
                        pipeline.cmd("HSET").arg(&[
                            config.gitee_repo.to_owned(),
                            filepath.to_owned(),
                            fileurl.to_owned(),
                        ]); 
                    }
                    pipeline.execute_async(&mut redisconn).await?;
                }
                None => {}
            }
        }
        None => {}
    }

    Ok(())
}

//图C用自定义route handler
impl RocketGiteePicturesHandler {
    pub async fn routes(
        path: &'static str,
        config: RocketGiteePicturesWrapperConfig,
    ) -> Vec<Route> {
        let task_config = config.clone();

        rocket::tokio::spawn(async move {
            println!("加载gitee文件路径到 redis缓存..");
            //获取连接池
            let task_pool = redis_pool_wrapper::get_pool(
                &task_config.redis_password,
                &task_config.redis_host,
                &task_config.redis_port,
            );
            //加载gitee文件路径到 redis缓存
            loop {
                load_git_files_path_to_redis(&task_config, &task_pool)
                    .await
                    .unwrap();

                rocket::tokio::time::sleep(std::time::Duration::from_millis(
                    task_config.gitee_refresh_interval as u64,
                ))
                .await;
            }
        });

        //获取连接池
        let web_pool = redis_pool_wrapper::get_pool(
            &config.redis_password,
            &config.redis_host,
            &config.redis_port,
        );

        let handler = Self {
            config: config.clone(),
            //多线程可变字段  RefCell，多线程加  Mutex, Clone 加 Arc
            redis_pool: web_pool,
        };
        //传递配置参数
        vec![Route::new(Get, &path, handler)]
    }
}

#[rocket::async_trait]
impl route::Handler for RocketGiteePicturesHandler {
    async fn handle<'r>(&self, req: &'r Request<'_>, _data: Data<'r>) -> route::Outcome<'r> {
        //获取图片路径
        let image_path = req
            .segments::<PathBuf>(0..)
            .unwrap()
            .to_str()
            .unwrap()
            .replace("\\", "/");

        println!("image_path={}", &image_path);

        //redis 连接池
        let redis_pool = &self.redis_pool;
        //获取连接
        let mut redisconn = redis_pool.get().await.unwrap();
        let v = cmd("HGET")
            .arg(&[self.config.gitee_repo.to_owned(), image_path.to_owned()])
            .query_async::<String>(&mut redisconn)
            .await;
        //文件链接
        let mut file_url: String = String::from("");
        match v {
            Ok(s) => {
                file_url = s.clone();
            }
            Err(_e) => {}
        }

        if file_url == "" {
            return route::Outcome::from(req, "");
        }

        //根据链接获取图片数据
        let response_body = reqwest::get(format!(
            "{}?access_token={}",
            &file_url, &self.config.gitee_token
        ))
        .await
        .unwrap()
        .text()
        .await
        .unwrap();

        let response_body_json: serde_json::Value = serde_json::from_str(&response_body).unwrap();
        let response_body_content = response_body_json.get("content").unwrap().as_str().unwrap();
        let response_body_bytes = base64::decode(response_body_content).unwrap();
        println!("file_url={}", &file_url);

        route::Outcome::from(
            req,
            (
                ContentType::parse_flexible("image/webp").unwrap(),
                response_body_bytes,
            ),
        )
    }
}
